#include "HttpServer.h"

using namespace std::placeholders;

HttpServer::HttpServer()
    : m_http_listener(std::bind(&HttpServer::OnAccept, this, _1, _2), 256)
{
    m_http_handler_setting.on_connected = std::bind(&HttpServer::OnConnected, this, _1);
    m_http_handler_setting.on_close = std::bind(&HttpServer::OnClose, this, _1);
    m_http_handler_setting.on_timeout = std::bind(&HttpServer::OnTimeout, this, _1);
    m_http_handler_setting.on_message = std::bind(&HttpServer::OnMessage, this, _1, _2);
}
HttpServer::~HttpServer()
{
    for (auto& item : m_handlerList)
    {
        item.second->Close();  // 关闭所有连接
    }
    m_handlerList.clear();
}

int HttpServer::Start(const char* ip, std::uint16_t port, HttpMessageCallback&& message_cb)
{
	if (m_http_listener.Listen(ip, port) < 0)
	{
		return -1;
	}

	int iret = CCReactor::Instance()->AttachPoller(&m_http_listener);
	if (iret != 0)
	{
		log_boot("Attach epoll Failed. ip=[%s:%d]", m_http_listener._bindAddr, m_http_listener._bindPort);
		return -1;
	}

    m_message_cb = std::move(message_cb);

    return 0;
}

int HttpServer::Response(std::uint32_t handle, stHttpResponse&& response)
{
    auto it = m_handlerList.find(handle);
    if (it == m_handlerList.end())
    {
        return -1;
    }
    if (it->second == nullptr)
    {
        return -1;
    }
	return it->second->Response(std::move(response));
}

int HttpServer::OnConnected(HttpHandler* pHandler)
{
    return 0;
}

int HttpServer::OnClose(HttpHandler* pHandler)
{
    if (pHandler == nullptr)
    {
        log_notice("HttpHandler is null");
        return -1;
    }
    m_handlerList.erase(pHandler->m_HandlerID);
    return 0;
}
int HttpServer::OnTimeout(HttpHandler* pHandler)
{
    log_error("timeout:%u", pHandler->m_HandlerID);
    return 0;
}
int HttpServer::OnMessage(HttpHandler* pHandler, stHttpRequest&& http_data)
{
    assert(pHandler);
	// if this is a preflight request
	if(0 == http_data.method.compare("OPTIONS")){
        stHttpResponse response;
        response.heads["Access-Control-Allow-Origin"] = "*";
        response.heads["Access-Control-Allow-Methods"] = "POST,GET";
        response.heads["Access-Control-Allow-Headers"] = "*";
        response.heads["Content-Type"] = "text/html; charset=utf-8";
        response.state = 200;
        log_debug("id:%u,req:%s,resp:%s", pHandler->m_HandlerID, http_data.ToString().c_str(), response.ToString().c_str());
		return pHandler->Response(std::move(response));
	}
    try
    {
        if (m_message_cb)
        {
            return m_message_cb(pHandler->m_HandlerID, std::move(http_data));
        }
        else
        {
            log_debug("no handler,id:%u,req:%s", pHandler->m_HandlerID, http_data.ToString().c_str());
        }
    }
    catch(const std::exception& e)
    {
        log_debug("exception:%s,id:%u,req:%s", e.what(), pHandler->m_HandlerID, http_data.ToString().c_str());
    }
    catch(...)
    {
        log_debug("unknown exception,id:%u,req:%s", pHandler->m_HandlerID, http_data.ToString().c_str());
    }
}
int HttpServer::OnAccept(int netfd, struct sockaddr_in* peer)
{
    HttpHandler* p_handler = CreateHandler(netfd, peer);
    if (NULL == p_handler)
    {
        log_error ("create HttpHandler object failed, client[%s:%d], fd[%d]", inet_ntoa(peer->sin_addr), peer->sin_port, netfd);
        ::close (netfd);
        return -1;
    }
    
    p_handler->SetIP(peer->sin_addr.s_addr);
    std::string ip = inet_ntoa(peer->sin_addr);
    p_handler->SetSIP(ip);
    p_handler->SetPort(ntohs(peer->sin_port));
    p_handler->SetNetfd(netfd);

    AcceptNewHandler(p_handler);
    
    if( p_handler->OnConnected()<0 )
    {
    	log_notice ("HttpHandler:OnConnect() failed, client[%s:%d], fd[%d]", inet_ntoa(peer->sin_addr), peer->sin_port, netfd);
    	p_handler->handle_close();
        return -2;
    }
    
    if (CCReactor::Instance()->AttachPoller(p_handler) < 0)
    {
    	log_error ("AttachPoller failed, client[%s:%d], fd[%d]", inet_ntoa(peer->sin_addr), peer->sin_port, netfd);
    	p_handler->handle_close();
        return -3;
    }
    return 0;
}
HttpHandler* HttpServer::CreateHandler(int netfd, struct sockaddr_in* peer)
{
    return new HttpHandler(m_http_handler_setting);
}
int HttpServer::AcceptNewHandler(HttpHandler* pHandler)
{
	static unsigned int flow_id = 0;
	if (++flow_id > 0x7fffffee)
		flow_id = 1;
	pHandler->m_HandlerID = flow_id;
	m_handlerList[flow_id] = pHandler;

	return 0;
}









